/**
 * @Project : algorithm-learning
 * @Author : Ruoyu Wang
 * @User : Momenta
 * @DateTime : 2024/3/19 20:04
 */

//小苯来到了一座山脉，山脉中有n座山，每座山都有一个高度hi。
//有些山之间有路径连接，例如如果a号山和6号山之间有路径，如果小苯想的话，他可以从a山走到b山，同样的，也可以从b山走到a山。
//但小苯很懒，如果两座山之间的高度差大于一定的值k，他就不会走这条路(无论是上山还是下山)。
//形式化的即:|ha-hb|>k的话，小苯便不会走这条路。
//现在他提出了q次询问，每次询问他都会给出一组(a,b,k)，
//他想知道，如果他从a山出发，高度差大于k的路径他不走，能否找到一条路使得他能走到b山呢，请你帮帮他吧。
//
//输入描述
//  输入包含1+m+q行。第一行三个正整数n(1≤ n ≤2x10^5),m(1≤ min(n*(n-1)/2,2x10),q(1≤ q ≤2x10^5)
//  分别表示山脉中山的个数n，山脉中山与山之间的路径数量m，小苯的询问次数q
//  接下来一行输入n个正整数hi(1≤ hi ≤ 10^9)，表示每座山的高度。
//  接下来m行，每行两个正整数u,v(1 ≤ u,v ≤n,u≠v)，表示u号山到v号山有路径连接。
//  接下来q行，每行三个正整数a,b,k(1 ≤ a,b ≤ n,a ≠ b)，(1≤ k ≤10^9)，分别表示小苯每次询问给出的信息。
//输出描述
//  输出包含9行，对于每次小苯的询问，如果他可以从a走到b则输出"YES"，否则输出"NO"。
//补充说明
//  注意，输入并不保证同一对山a,b中只有一条路径。
//
//示例 1
//输入
//5 6 5
//3 4 3 6 5
//1 2
//1 3
//2 4
//3 4
//3 5
//4 5
//1 4 1
//1 4 2
//1 4 3
//3 4 2
//1 5 1
//输出
//No
//Yes
//Yes
//Yes
//No

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int N = 2 * 1e5 + 10;
int f[N];
int n, m, q;

void init() {
    for (int i = 1; i <= n; ++i) {
        f[i] = i;
    }
}

int find(int x) {
    if (f[x] != x) f[x] = find(f[x]);
    return f[x];
}


int main() {
    scanf("%d%d%d", &n, &m, &q);

    int heights[n + 1];
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &heights[i]);
    }

    vector<vector<int>> edges;
    for (int i = 0; i < m; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        edges.push_back({u, v, abs(heights[u] - heights[v])});
    }

    // 按高度差对边进行排序
    sort(edges.begin(), edges.end(), [](vector<int> a, vector<int> b) {
        return a[2] < b[2];
    });

    for (int i = 0; i < q; ++i) {
        int a, b, k;
        scanf("%d%d%d", &a, &b, &k);

        // 每次查询之前重置并查集
        init();

        for (auto edge: edges) {
            if (edge[2] > k) break; // 高度差大于k时停止合并
            f[edge[0]] = find(edge[1]);
        }

        // 检查是否属于同一个集合
        puts(find(a) == find(b) ? "YES" : "NO");
    }

    return 0;
}

